//|||||||||||||||||||||||||||||||||||||||||||||||

#ifndef GAME_STATE_HPP
#define GAME_STATE_HPP

//|||||||||||||||||||||||||||||||||||||||||||||||

#include "AppState.hpp"

#include "DotSceneLoader.hpp"

#include <OgreSubEntity.h>
#include <OgreMaterialManager.h>
#include <Terrain/OgreTerrain.h>
#include <Terrain/OgreTerrainGroup.h>

//bullet includes
#include "OgreBulletDynamicsRigidBody.h"
#include "Shapes/OgreBulletCollisionsStaticPlaneShape.h"
#include "Shapes/OgreBulletCollisionsBoxShape.h"  
#include "Shapes/OgreBulletCollisionsTerrainShape.h"
#include "Shapes/OgreBulletCollisionsCompoundShape.h"
#include "OgreBulletDynamicsWorld.h"
#include "Debug/OgreBulletCollisionsDebugDrawer.h"
#include "Constraints/OgreBulletDynamicsRaycastVehicle.h"

//|||||||||||||||||||||||||||||||||||||||||||||||

//paged geometry
#include "PagedGeometry/PagedGeometryConfig.h"
//Include PagedGeometry headers that will be needed
#include "PagedGeometry/PagedGeometry.h"
#include "PagedGeometry/BatchPage.h"
#include "PagedGeometry/ImpostorPage.h"
//#include "PagedGeometry/TreeLoader3D.h"
//#include "PagedGeometry/TreeLoader2D.h"
#include "PagedGeometry/GrassLoader.h"
//PagedGeometry's classes and functions are under the "Forests" namespace

using namespace Forests;

class GameState : public AppState
{
public:
	GameState();

	DECLARE_APPSTATE_CLASS(GameState)

	void enter();
	void exit();
	void createVeg();
	void createPart();

	bool keyPressed(const OIS::KeyEvent &keyEventRef);
	bool keyReleased(const OIS::KeyEvent &keyEventRef);

	bool mouseMoved(const OIS::MouseEvent &arg);
	bool mousePressed(const OIS::MouseEvent &arg, OIS::MouseButtonID id);
	bool mouseReleased(const OIS::MouseEvent &arg, OIS::MouseButtonID id);

	void update(double timeSinceLastFrame);

private:

	bool										m_bQuit;

	//Camera
	Ogre::Camera*								m_pCamera;

	//Particles
	//Ogre::ParticleSystem*								pSys2;
	//Ogre::SceneNode*									fNode2;

	//PagedGeometry
	void exitPagedGeometry();
	//PagedGeometry* m_pTrees;
	//PagedGeometry* m_pTrees2;
	//PagedGeometry* m_pBushes;
	PagedGeometry *m_pGrass;
	GrassLoader *m_pGrassLoader;

	// OgreBullet
	void exitBullet();
	void bullet();
	void updateBullet(double timeSinceLastFrame);

	Ogre::Vector3								m_CarPosition;
	Ogre::Vector3								chassisShift;
	float										connectionHeight;

	OgreBulletDynamics::DynamicsWorld			*mWorld;   
    OgreBulletCollisions::DebugDrawer			*debugDrawer;
    int											mNumEntitiesInstanced;
    std::deque<OgreBulletDynamics::RigidBody *>         mBodies;
    std::deque<OgreBulletCollisions::CollisionShape *>  mShapes;
	float										m_Gravity;
	Ogre::AxisAlignedBox						bounds;
	Ogre::Vector3								gravityVector;
	OgreBulletCollisions::HeightmapCollisionShape *mTerrainShape;
	OgreBulletDynamics::RigidBody				*defaultTerrainBody;

	OgreBulletDynamics::WheeledRigidBody        *mCarChassis;
    OgreBulletDynamics::VehicleTuning	        *mTuning;
    OgreBulletDynamics::VehicleRayCaster	    *mVehicleRayCaster;
    OgreBulletDynamics::RaycastVehicle	        *mVehicle;

    Ogre::Entity								*mChassis;
    Ogre::Entity								*mWheels[4];
    Ogre::SceneNode								*mWheelNodes[4];
	Ogre::SceneNode								*node;


    int											mWheelsEngine[4];
    int											mWheelsEngineCount;
    int											mWheelsSteerable[4];
    int											mWheelsSteerableCount;

    float										mEngineForce;
    float										mSteering;

    int											mWheelEngineStyle;
    int											mWheelSteeringStyle;

    bool										mSteeringLeft;
    bool										mSteeringRight;
	bool										mSteeringCenter;

	float										terrainBodyRestitution;
	float										terrainBodyFriction;

};

//|||||||||||||||||||||||||||||||||||||||||||||||

#endif

//|||||||||||||||||||||||||||||||||||||||||||||||